#include <stdlib.h>
#include "S_List.h"

int IsEmpty(S_List* list)
{
    return list == NULL || list->len == 0;
}

S_List* InitList()
{
    S_List *list = (S_List *)malloc(sizeof(S_List));
    list->head = NULL;
    list->len = 0;
    return list;
}

void Insert_Front(S_List *list, ElementType data)
{
    S_ListNode *newElement = (S_ListNode *)malloc(sizeof(S_ListNode));
    newElement->data = data;
    newElement->next = list->head;
    list->head = newElement;
    ++list->len;
}

void Insert_Back(S_List *list, ElementType data)
{
    S_ListNode *newElement = (S_ListNode *)malloc(sizeof(S_ListNode));
    newElement->data = data;
    newElement->next = NULL;
    S_ListNode **tpNode = &list->head;
    while(*tpNode != NULL)
    {
        tpNode = &(*tpNode)->next;
    }
    *tpNode = newElement;
    ++list->len;
}

void Insert_Before(S_List *list, ElementType findData, ElementType data)
{
    if(IsEmpty(list))
    {
        return;
    }        
    S_ListNode **tpNode = &list->head;
    while (*tpNode != NULL)
    {
        if((*tpNode)->data == findData)
        {
            S_ListNode *newNode = (S_ListNode *)malloc(sizeof(S_ListNode));
            newNode->data = data;
            newNode->next = *tpNode;
            *tpNode = newNode;
            ++list->len;
            return;
        }
        tpNode = &(*tpNode)->next;
    }
}

void Insert_After(S_List *list, ElementType findData, ElementType data)
{
    if(IsEmpty(list))
    {
        return;
    }        
    S_ListNode **tpNode = &list->head;
    while (*tpNode != NULL)
    {
        if((*tpNode)->data == findData)
        {
            S_ListNode *newNode = (S_ListNode *)malloc(sizeof(S_ListNode));
            newNode->data = data;
            newNode->next = (*tpNode)->next;
            (*tpNode)->next = newNode;
            ++list->len;
            return;
        }
        tpNode = &(*tpNode)->next;
    }
}

void Remove_Front(S_List *list)
{
    if(IsEmpty(list))
    {
        return;
    }
    S_ListNode *tpNode = list->head;
    list->head = tpNode->next;
    free(tpNode);
    --list->len;
}

void Remove_Back(S_List *list)
{
    if(IsEmpty(list))
    {
        return;
    }
    S_ListNode **tpNode = &list->head;
    while(*tpNode != NULL)
    {
        if((*tpNode)->next == NULL)
        {
            S_ListNode *delNode = *tpNode;
            *tpNode = (*tpNode)->next;
            free(delNode);
            --list->len;
            return;
        }
        tpNode = &(*tpNode)->next;
    }
}

void Remove(S_List* list, ElementType findData)
{
    if(IsEmpty(list))
    {
        return;
    }
    S_ListNode **tpNode = &list->head;
    while (*tpNode != NULL)
    {
        if((*tpNode)->data == findData)
        {
            S_ListNode *delNode = *tpNode;
            *tpNode = (*tpNode)->next;
            free(delNode);
            --list->len;
            return;
        }
        tpNode = &(*tpNode)->next;
    }    
}

S_ListNode *GetNodeByElement(S_List *list, ElementType findData)
{
    if(IsEmpty(list))
    {
        return NULL;
    }
    S_ListNode *tpNode = list->head;
    while(tpNode != NULL)
    {
        if(tpNode->data == findData)
        {
            return tpNode;
        }
        tpNode = tpNode->next;
    }
    return NULL;
}

S_ListNode *GetNodeByIndex(S_List *list, int index)
{
    if(IsEmpty(list) || index < 0 || list->len < index)
    {
        return NULL;
    }
    int i = 0;
    S_ListNode *tpNode = list->head;
    while(tpNode != NULL)
    {
        if(i == index)
        {
            return tpNode;
        }
        tpNode = tpNode->next;
        ++i;
    }
    return NULL;
}

int SetDataByIndex(S_List *list, int index, ElementType newData)
{
    if(index < 0 || list->len < index)
    {
        return 0;
    }
    S_ListNode *tpNode = GetNodeByIndex(list, index);
    if(tpNode != NULL)
    {
        tpNode->data = newData;
        return 1;        
    }
    return 0;
}

int SetDataByElement(S_List *list, ElementType findData, ElementType newData)
{
    if(IsEmpty(list))
    {
        return 0;
    }
    S_ListNode *tpNode = GetNodeByElement(list, findData);
    if(tpNode != NULL)
    {
        tpNode->data = newData;
        return 1;
    }
    return 0;
}